package br.ufpe.cin.imlm2.jbeat.paths.report;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import br.ufpe.cin.imlm2.jbeat.paths.ExceptionPath;


public final class PathMetrics {

	public static ExceptionPath longestPath( Collection<ExceptionPath> paths ) {
		if ( paths.size() == 0 || paths == null)
			return null;
		ExceptionPath maxPath = paths.iterator().next();
		for ( ExceptionPath exceptionPath : paths ) {
			if ( maxPath.length() < exceptionPath.length() ) {
				maxPath = exceptionPath;
			}
		}
		return maxPath;
	}
	
	public static ExceptionPath shortestPath( Collection<ExceptionPath> paths ) {
		if ( paths.size() == 0 || paths == null)
			return null;
		ExceptionPath smallestPath = paths.iterator().next();
		for ( ExceptionPath exceptionPath : paths ) {
			if ( smallestPath.length() > exceptionPath.length() ) {
				smallestPath = exceptionPath;
			}
		}
		return smallestPath;
	}
	
	public static List<ExceptionPath> shortestPaths(Collection<ExceptionPath> paths){
		if ( paths.size() == 0 || paths == null)
			return null;
		List<ExceptionPath> shortestPaths = new ArrayList<ExceptionPath>();
		int shortestLength = shortestPath(paths).length();
		for (ExceptionPath exceptionPath : paths) {
			if(exceptionPath.length() == shortestLength){
				shortestPaths.add(exceptionPath);
			}
		}
		return shortestPaths;
	}
	
	/**
	 * Returns all the longest paths found in the input collection.
	 * @param paths
	 * @return all the longest paths, null if paths.size() == 0 or paths == null
	 */
	public static List<ExceptionPath> longestPaths(Collection<ExceptionPath> paths){
		if ( paths.size() == 0  || paths == null)
			return null;
		List<ExceptionPath> longestPaths = new ArrayList<ExceptionPath>();
		int longestLength = longestPath(paths).length();
		for (ExceptionPath exceptionPath : paths) {
			if(exceptionPath.length() == longestLength){
				longestPaths.add(exceptionPath);
			}
		}
		return longestPaths;
	}

	/**
	 * Returns all paths such that for each path <b>p</b> in <code><b>paths</b></code> if <br>
	 * <b>p</b>.length() == ceil(averagePathLength) or 
	 * <b>p</b>.length() == floor(averagePathLength) <br>
	 * then <b>p</b> shall be in the returned collection.
	 * @param paths
	 * @return all paths that meet the above criterion or null if paths.size() == 0 or paths == null
	 */
	public static List<ExceptionPath> averagePaths(Collection<ExceptionPath> paths) {
		if ( paths.size() == 0 || paths == null)
			return null;
		List<ExceptionPath> avgPaths = new ArrayList<ExceptionPath>();
		float avgLength = avgPathLength(paths);
		for (ExceptionPath exceptionPath : paths) {
			if(exceptionPath.length() == Math.ceil(avgLength) || 
					exceptionPath.length() == Math.floor(avgLength)){
				avgPaths.add(exceptionPath);
			}
		}
		return avgPaths;
		
	}

	public static float avgPathLength( Collection<ExceptionPath> paths ) {
		if ( paths.size() == 0 )
			return 0;
	
		float medium = 0;
		for ( ExceptionPath p : paths ) {
			medium += p.length();
		}
	
		return medium / paths.size();
	}

	public static int numberOfCompletePaths( Collection<ExceptionPath> paths ) {
		int number = 0;
		for ( ExceptionPath exceptionPath : paths ) {
			if ( exceptionPath.isComplete() )
				number++;
		}
		return number;
	}

}
